package com.jwdemo
{
	// Simple GameObject Manager - using Double Linked List Class
	// Singleton GameObject Manager used to handle explosions, bullets and nasties (TODO).
	// All these objects must implement the InfGameObject interface.
	
	// Added a Couple of static calls to add Explosoins and Fire Bullets -
	// to our game scene, namely : -
	// GameObjectManager.Fire, GameObjectManager.Explode

	// TODO - Partition updates and rendering around a certain region
	// ie. Nasties 'offscreen' will not be updated or rendered.
	// 'offscreen' will be definable in terms of screen dimensions.
	
	import com.jwdemo.LinkedList;
	
	public class GameObjectManager
	{
		private static var gMan:GameObjectManager  ;
		
		private var gameobjectlist : LinkedList ;
		
		
		
		function GameObjectManager()
		{
			gameobjectlist	=	new LinkedList() ;
			
		}
		
		
		public static function Init() : void
		{
			gMan	=	new GameObjectManager() ;
		}
		
		public static function add(gameobject:InfGameObject) : InfGameObject
		{
			gMan.gameobjectlist.add(gameobject) ;
			return gameobject ;
		}
		
		
		
		public static function Update(dt:Number) : void
		{
			
			var removeList:LinkedList	=	new LinkedList() ; 
			var list:LinkedList 		=	gMan.gameobjectlist	;
			for (var it:Object = list.Iterator() ; it.hasElements() ; it.next())
			{
				var node:Node = it.getCurrent() ;
				
				var gameobject:InfGameObject	= node.getData() ;
				if (gameobject.isAlive())
				{
					gameobject.update(dt) ;
				} else
				{
					removeList.add({list:list,element:node,gameobject:gameobject}) ;
				}	
				
			}
			
			// finished updating - now remove those that have finished.
			for (var itr:Object = removeList.Iterator(true) ; itr.hasElements() ; itr.next())
			{
				var removeInfo:Object = itr.getCurrent() ;
				removeInfo.gameobject.applyDamage(100) ;
				removeInfo.list.remove(removeInfo.element) ;
			}
			
			
		}
		
				
		public static function Render(rHelper:RenderHelper) : void
		{
			var list:LinkedList	=	gMan.gameobjectlist	 ;
			
			for (var it:Object = list.Iterator(true) ; it.hasElements() ; it.next())
			{
				var gameobject:InfGameObject = it.getCurrent() ;
				gameobject.render(rHelper)
			}
			
			
		}

		
		// Building up neighbourhood table - 
		
		private static function BuildNeighbourHoodTable(numberOfColumns:uint, numberOfRows:uint) : Array
		{
			var neighbourTable : Array	=	new Array() ;
			
			var _CA : Function	=	function(col:int,row:int) : int
									{
										var screensPerRow:uint	=	numberOfColumns ;
										var screenNumber:int	=	((row  - 1)* screensPerRow + (col - 1))  ;
										return screenNumber	;	
									} ;

			for (var row:uint = 0 ; row < numberOfRows ; row++)
			{
				for (var column:uint = 0 ; column < numberOfColumns ; column++)
				{
					var neighbours : Array		=	new Array() ;

					if (row + 1 < numberOfRows)
					{
						neighbours.push(_CA(column, row + 1)) ;
						if (column + 1 < numberOfColumns)
						{
							neighbours.push(_CA(column + 1, row + 1)) ;
						}
						if (column - 1 >= 0)
						{
							neighbours.push(_CA(column - 1, row + 1)) ;
						}
					}
					
					if (row - 1 >= 0)
					{
						neighbours.push(_CA(column, row - 1)) ;
						
						if (column + 1 < numberOfColumns)
						{
							neighbours.push(_CA(column + 1, row - 1)) ;
							
						}
						if (column - 1 >= 0)
						{
							neighbours.push(_CA(column - 1, row - 1)) ;
						}
					}
					
					if (column + 1 < numberOfColumns) 
					{
						neighbours.push(_CA(column + 1, row)) ;
					}
					
					if (column - 1 >= 0) 
					{
						neighbours.push(_CA(column - 1, row)) ;
					}
					var ca:Number = _CA(column,row) ;

					neighbourTable[ca]		=	new Array() ;
					neighbourTable[ca][ca]	=	true	;
					for (var idx:uint = 0 ; idx < neighbours.length ; idx++)
					{	
						var nghbr:int 	=	neighbours[idx] ;
						neighbourTable[ca][nghbr] = true	
					}
				}
			}

			return	neighbourTable ;

		}
		
		private static function CalcRegions() : void
		{
	
		}
		
		
		
		// Public functions - allowing us to add game object entities.
		// Explosions/Bullets
		
		public static function Explode(xpos:Number, ypos:Number) : InfGameObject
		{
			return GameObjectManager.add(new Explosion(xpos,ypos)) ;

		}
		
		// Bullets
		public static function Fire(	owner:Enemy, 
										damage:Number, 
										velocity:Number, 
										direction:Number, 
										duration: Number, 
										animation:TextureAnim,
										scale:Number = 1, 
										radius:Number = 10) : InfGameObject
		{
			GameSounds.PlaySFX("fire") ;
			
			//BulletManager.Fire				=	function(owner,damage,vel,angle,duration,animation,scale,radius)
			return GameObjectManager.add(new Bullet(owner,damage,velocity,direction,duration,animation,scale,radius)) ;
		}
		

		
	}
}

